//+------------------------------------------------------------------+
//|                                                    WndClient.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "WndContainer.h"                    // 容器窗口基类（提供子控件管理能力）
#include "Panel.h"                           // 面板类（用于容器背景）
#include "Scrolls.h"                         // 滚动条类（垂直 CScrollV / 水平 CScrollH）

//+------------------------------------------------------------------+
//| CWndClient 类：MQL5 带滚动条的容器基类                              |
//| 核心能力：继承容器类 CWndContainer，扩展垂直/水平滚动条功能，支持     |
//|           当子控件或内容超出容器可视范围时通过滚动条查看，同时管理     |
//|           背景面板与滚动条的联动布局，是列表、表格等可滚动控件的父类   |
//| 适用场景：作为需要滚动功能的复杂控件（如 ListView、RadioGroup）的基类，|
//|           不直接实例化，需通过子类实现具体内容展示逻辑               |
//+------------------------------------------------------------------+
class CWndClient : public CWndContainer
  {
protected:
   // 滚动状态标志（保护，子类可访问）
   bool              m_v_scrolled;          // 垂直滚动启用标志：true=支持垂直滚动，false=不支持
   bool              m_h_scrolled;          // 水平滚动启用标志：true=支持水平滚动，false=不支持

   // 子控件（保护，子类可操作）
   CPanel            m_background;          // 容器背景面板（用于装饰和界定容器区域）
   CScrollV          m_scroll_v;            // 垂直滚动条（内容超出高度时显示）
   CScrollH          m_scroll_h;            // 水平滚动条（内容超出宽度时显示）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化带滚动条容器的默认状态
    * @details 初始化滚动状态标志（垂直/水平滚动均禁用），子控件（背景、滚动条）待 Create 时创建
    */
                     CWndClient(void);

   /**
    * @brief 析构函数：清理带滚动条容器的资源
    * @details 依赖父类 CWndContainer 的析构逻辑，自动释放子控件（背景、滚动条）
    */
                    ~CWndClient(void);

   //----------------------------------------------------------------
   // 控件创建：初始化容器、背景及滚动条
   //----------------------------------------------------------------
   /**
    * @brief 创建带滚动条的容器控件
    * @param chart [in] 目标图表ID（0 表示当前活跃图表）
    * @param name [in] 控件唯一标识名（图表内不可重复）
    * @param subwin [in] 绑定的子窗口编号（0 = 主窗口，≥1 = 指标子窗口）
    * @param x1 [in] 左上角X坐标（像素，相对于图表窗口）
    * @param y1 [in] 左上角Y坐标（像素）
    * @param x2 [in] 右下角X坐标（像素）
    * @param y2 [in] 右下角Y坐标（像素）
    * @return bool - 创建结果：true=成功（父类初始化+背景创建+滚动条按需创建），false=失败
    * @note 若创建时已启用滚动（m_v_scrolled/m_h_scrolled 为 true），会自动创建对应滚动条
    */
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);

   //----------------------------------------------------------------
   // 事件处理：响应容器及滚动条相关事件
   //----------------------------------------------------------------
   /**
    * @brief 处理容器及滚动条事件（如滚动条显示/隐藏、滚动操作等）
    * @param id [in] 事件ID（如 ON_SCROLL_INC 表示滚动增量事件）
    * @param lparam [in] 长整数参数（事件相关数据）
    * @param dparam [in] 双精度参数（事件相关数据）
    * @param sparam [in] 字符串参数（通常为控件名称，用于识别事件来源）
    * @return bool - 处理结果：true=事件已处理，false=未处理（交由父类处理）
    */
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

   //----------------------------------------------------------------
   // 背景样式配置：设置背景色、边框色及边框类型
   //----------------------------------------------------------------
   /**
    * @brief 设置容器背景色
    * @param value [in] 目标背景色（RGB 颜色值）
    * @return bool - 设置结果：true=成功（同步到背景面板 m_background），false=失败
    */
   virtual bool      ColorBackground(const color value);

   /**
    * @brief 设置容器边框色
    * @param value [in] 目标边框色（RGB 颜色值）
    * @return bool - 设置结果：true=成功（同步到背景面板 m_background），false=失败
    */
   virtual bool      ColorBorder(const color value);

   /**
    * @brief 设置容器边框类型
    * @param flag [in] 目标边框类型（ENUM_BORDER_TYPE 枚举值，如 BORDER_FLAT 扁平边框）
    * @return bool - 设置结果：true=成功（同步到背景面板 m_background），false=失败
    */
   virtual bool      BorderType(const ENUM_BORDER_TYPE flag);

   //----------------------------------------------------------------
   // 滚动功能配置：启用/禁用垂直/水平滚动
   //----------------------------------------------------------------
   /**
    * @brief 获取垂直滚动启用状态
    * @return bool - 垂直滚动状态：true=已启用，false=已禁用
    */
   virtual bool      VScrolled(void);

   /**
    * @brief 启用/禁用垂直滚动功能
    * @param flag [in] 目标状态：true=启用（创建垂直滚动条），false=禁用（销毁垂直滚动条）
    * @return bool - 设置结果：true=成功（滚动条创建/销毁+布局调整），false=失败
    * @note 启用时会自动调整水平滚动条宽度（若存在），避免两者重叠
    */
   virtual bool      VScrolled(const bool flag);

   /**
    * @brief 获取水平滚动启用状态
    * @return bool - 水平滚动状态：true=已启用，false=已禁用
    */
   virtual bool      HScrolled(void);

   /**
    * @brief 启用/禁用水平滚动功能
    * @param flag [in] 目标状态：true=启用（创建水平滚动条），false=禁用（销毁水平滚动条）
    * @return bool - 设置结果：true=成功（滚动条创建/销毁+布局调整），false=失败
    * @note 启用时会自动调整垂直滚动条高度（若存在），避免两者重叠
    */
   virtual bool      HScrolled(const bool flag);

   //----------------------------------------------------------------
   // 控件ID：设置与获取唯一标识（覆盖父类方法）
   //----------------------------------------------------------------
   /**
    * @brief 设置容器及子控件（滚动条）的ID
    * @param id [in] 容器的基础ID（滚动条ID会在此基础上递增，确保唯一性）
    * @return long - 已使用的ID数量（容器+滚动条占用的ID总数）
    */
   virtual long      Id(const long id);

   /**
    * @brief 获取容器的唯一ID
    * @return long - 容器ID（继承自 CWnd 类的 m_id）
    */
   virtual long      Id(void) const;

   //----------------------------------------------------------------
   // 控件状态：设置容器可见性（覆盖父类方法）
   //----------------------------------------------------------------
   /**
    * @brief 设置容器为可见状态
    * @return bool - 设置结果：true=成功（父类可见性设置+滚动条按需显示），false=失败
    * @note 仅当滚动功能启用时（m_v_scrolled/m_h_scrolled 为 true），对应滚动条才会显示
    */
   virtual bool      Show(void);

protected:
   //----------------------------------------------------------------
   // 子控件创建：创建背景及滚动条（保护，仅内部调用）
   //----------------------------------------------------------------
   /**
    * @brief 创建容器背景面板
    * @return bool - 创建结果：true=成功（背景初始化+添加到容器），false=失败
    * @note 背景面板默认填充整个容器区域，用于装饰和界定可视范围
    */
   virtual bool      CreateBack(void);

   /**
    * @brief 创建垂直滚动条
    * @return bool - 创建结果：true=成功（滚动条位置/尺寸配置+添加到容器），false=失败
    * @note 垂直滚动条默认位于容器右侧，高度自适应（避开水平滚动条区域）
    */
   virtual bool      CreateScrollV(void);

   /**
    * @brief 创建水平滚动条
    * @return bool - 创建结果：true=成功（滚动条位置/尺寸配置+添加到容器），false=失败
    * @note 水平滚动条默认位于容器底部，宽度自适应（避开垂直滚动条区域）
    */
   virtual bool      CreateScrollH(void);

   //----------------------------------------------------------------
   // 生命周期事件回调：处理容器尺寸变化（保护，仅子类可重写）
   //----------------------------------------------------------------
   /**
    * @brief 容器尺寸变化事件回调
    * @return bool - 处理结果：true=成功（背景尺寸更新+滚动条位置/尺寸调整），false=失败
    * @note 自动适配容器新尺寸，确保滚动条始终位于正确位置（右侧/底部）
    */
   virtual bool      OnResize(void);

   //----------------------------------------------------------------
   // 滚动条事件回调：处理滚动条显示/隐藏（保护，仅子类可重写）
   //----------------------------------------------------------------
   /**
    * @brief 垂直滚动条显示事件回调
    * @return bool - 处理结果：true=成功（子类可扩展以调整内容布局），false=失败（默认 true）
    */
   virtual bool      OnVScrollShow(void);

   /**
    * @brief 垂直滚动条隐藏事件回调
    * @return bool - 处理结果：true=成功（子类可扩展以调整内容布局），false=失败（默认 true）
    */
   virtual bool      OnVScrollHide(void);

   /**
    * @brief 水平滚动条显示事件回调
    * @return bool - 处理结果：true=成功（子类可扩展以调整内容布局），false=失败（默认 true）
    */
   virtual bool      OnHScrollShow(void);

   /**
    * @brief 水平滚动条隐藏事件回调
    * @return bool - 处理结果：true=成功（子类可扩展以调整内容布局），false=失败（默认 true）
    */
   virtual bool      OnHScrollHide(void);

   //----------------------------------------------------------------
   // 滚动操作回调：处理滚动条滚动事件（保护，仅子类可重写）
   //----------------------------------------------------------------
   /**
    * @brief 垂直滚动条向下滚动一行事件回调
    * @return bool - 处理结果：true=成功（子类需实现内容向下滚动逻辑），false=失败（默认 true）
    */
   virtual bool      OnScrollLineDown(void);

   /**
    * @brief 垂直滚动条向上滚动一行事件回调
    * @return bool - 处理结果：true=成功（子类需实现内容向上滚动逻辑），false=失败（默认 true）
    */
   virtual bool      OnScrollLineUp(void);

   /**
    * @brief 水平滚动条向左滚动一行事件回调
    * @return bool - 处理结果：true=成功（子类需实现内容向左滚动逻辑），false=失败（默认 true）
    */
   virtual bool      OnScrollLineLeft(void);

   /**
    * @brief 水平滚动条向右滚动一行事件回调
    * @return bool - 处理结果：true=成功（子类需实现内容向右滚动逻辑），false=失败（默认 true）
    */
   virtual bool      OnScrollLineRight(void);

   //----------------------------------------------------------------
   // 容器边界更新：同步容器矩形区域并触发尺寸变化（保护，仅内部调用）
   //----------------------------------------------------------------
   /**
    * @brief 更新容器的矩形边界（位置+尺寸）
    * @param rect [in] 新的矩形边界
    * @return bool - 处理结果：true=成功（更新边界+触发 OnResize()），false=失败
    */
   virtual bool      Rebound(const CRect &rect);
  };

//+------------------------------------------------------------------+
//| CWndClient 事件映射：关联子控件事件到处理函数（用于IDE智能提示）      |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CWndClient)
   ON_NAMED_EVENT(ON_SHOW, m_scroll_v, OnVScrollShow)    // 垂直滚动条显示 → 调用 OnVScrollShow
   ON_NAMED_EVENT(ON_HIDE, m_scroll_v, OnVScrollHide)    // 垂直滚动条隐藏 → 调用 OnVScrollHide
   ON_EVENT(ON_SCROLL_DEC, m_scroll_v, OnScrollLineUp)   // 垂直滚动条向上滚动 → 调用 OnScrollLineUp
   ON_EVENT(ON_SCROLL_INC, m_scroll_v, OnScrollLineDown) // 垂直滚动条向下滚动 → 调用 OnScrollLineDown
   ON_NAMED_EVENT(ON_SHOW, m_scroll_h, OnHScrollShow)    // 水平滚动条显示 → 调用 OnHScrollShow
   ON_NAMED_EVENT(ON_HIDE, m_scroll_h, OnHScrollHide)    // 水平滚动条隐藏 → 调用 OnHScrollHide
   ON_EVENT(ON_SCROLL_DEC, m_scroll_h, OnScrollLineLeft) // 水平滚动条向左滚动 → 调用 OnScrollLineLeft
   ON_EVENT(ON_SCROLL_INC, m_scroll_h, OnScrollLineRight)// 水平滚动条向右滚动 → 调用 OnScrollLineRight
EVENT_MAP_END(CWndContainer)
//+------------------------------------------------------------------+